package com.niconicod.ofb.actors;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.niconicod.ofb.utils.PhysicsUtils;
import com.niconicod.ofb.utils.flightmodel.DummyFlightModel;
import com.niconicod.ofb.utils.flightmodel.FlightModel;
import com.niconicod.ofb.utils.flightmodel.PhysicalFlightModel;

public class PlayerPlane extends Actor {

    private final Sprite sprite;
    private FlightModel flightModel;

    public PlayerPlane(Sprite sprite, FlightModel flightModel) {
        this.sprite = sprite;
        this.flightModel = flightModel;

//        System.out.println(sprite.getTexture().getMagFilter());
//        System.out.println(sprite.getTexture().getMinFilter());
        sprite.getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        sprite.draw(batch);
    }

    @Override
    protected void drawDebugBounds(ShapeRenderer shapes) {
        super.drawDebugBounds(shapes);
        shapes.circle(getCenterX(), getCenterY(), getHeight() / 20);
        Vector2 nose = flightModel.getNoseDirection();
        nose.setLength(getHeight());
        nose.add(getCenterX(), getCenterY());
    }

    @Override
    public void act(float delta) {
        super.act(delta);
        flightModel.act(delta);
        syncWithFlightModel();
        syncSprite();
        updateCamera();

    }

    private void syncWithFlightModel() {
        setRotation(flightModel.getAngleDeg());
        setCenterPosition(flightModel.getPosition());
    }

    private void syncSprite() {
        sprite.setOrigin(getOriginX(), getOriginY());
        sprite.setBounds(getX(), getY(), getWidth(), getHeight());
        sprite.setRotation(getRotation());
    }

    private void updateCamera() {
        getStage().getCamera().position.set(getCenter(), 0);
        getStage().getCamera().update();
    }

    private float getCenterX() {
        return getX() + getOriginX();
    }

    private float getCenterY() {
        return getY() + getOriginY();
    }

    private Vector2 getCenter() {
        return new Vector2(getCenterX(), getCenterY());
    }

    public void setCenterPosition(Vector2 position) {
        setX(position.x - getOriginX());
        setY(position.y - getOriginY());
    }

    private Vector2 getNoseDirection() {
        Vector2 direction = new Vector2(Vector2.Y);
        direction.rotateDeg(getRotation());
        return direction.nor();
    }

    public FlightModel getFlightModel() {
        return flightModel;
    }

    @Deprecated
    public static PlayerPlane createPhysicalInstance(Sprite sprite, Body body, float size) {
        FlightModel flightModel = null;
        PlayerPlane plane = new PlayerPlane(sprite, flightModel);
        plane.setCenterPosition(body.getPosition());
        plane.setSize(size, size);
        plane.setOrigin(size / 2, size / 2);
        return plane;
    }

    public static PlayerPlane createPhysicalInstance(Sprite sprite, Vector2 size, Vector2 position, World world) {

        Body body = PhysicsUtils.createBoxBody(world, size, position, 200);
        FlightModel flightModel = PhysicalFlightModel.createDefault(body, size.y);
//        PhysicalFlightModel flightModel = PhysicalFlightModel.createDefault(body, size.y);
        PlayerPlane plane = new PlayerPlane(sprite, flightModel);
        plane.setSize(size.x, size.y);
        plane.setOrigin(size.x / 2, size.y / 2);
        return plane;
    }

    public static PlayerPlane getDummyInstance(Sprite sprite, Vector2 size, Vector2 position){
        FlightModel flightModel = new DummyFlightModel(position, Vector2.Y, 20, 30);
        PlayerPlane plane = new PlayerPlane(sprite, flightModel);
        plane.setSize(size.x, size.y);
        plane.setOrigin(size.x / 2, size.y / 2);
        return plane;
    }
}
